using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace Microsoft.Samples.Windows.Forms.Navigation
{
	/// <summary>
	/// The WinForms Explorer: an Explorer-like window for browsing Windows Forms pages.
	/// </summary>
    public class Explorer : System.Windows.Forms.Form
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.ToolBarButton homeButton;
		private System.Windows.Forms.ToolBarButton forwardButton;
		private System.Windows.Forms.ToolBarButton backButton;
		private System.Windows.Forms.ImageList toolBarImages;
		protected System.Windows.Forms.ToolBar navigationToolBar;
		private System.Windows.Forms.MenuItem fileExit;
		private System.Windows.Forms.MenuItem fileMenu;
    protected System.Windows.Forms.MainMenu menuBar;
		private EventHandler backButtonMenuItemHandler;
		private EventHandler forwardButtonMenuItemHandler;
		private Microsoft.Samples.Windows.Forms.Navigation.Frame frame;
		private System.Windows.Forms.MenuItem goMenu;
		private System.Windows.Forms.MenuItem goHome;
		private System.Windows.Forms.MenuItem goBack;
		private System.Windows.Forms.MenuItem goForward;
		private System.Windows.Forms.MenuItem goMenuSeparator;
		private System.Windows.Forms.ToolBarButton toolBarSeparator;

        private string applicationName = null;

		/// <summary>
		/// The maximum number of items that will be shown on the dropdown menus for
		/// the toolbar's Back and Forward buttons. This is set to 9, because that's
		/// what Internet Explorer uses.
		/// </summary>
		private const int MAX_TOOLBAR_DROPDOWN_MENU_ITEMS = 9;

		/// <summary>
		/// Create a new Explorer window.
		/// </summary>
		public Explorer()
		{
			InitializeComponent();

			// Set up event handlers that will get used for all items on the Back and Forward dropdown menus.
			backButtonMenuItemHandler = new EventHandler(this.BackButtonMenuItem_click);
			forwardButtonMenuItemHandler = new EventHandler(this.ForwardButtonMenuItem_click);
		}

		/// <summary>
		/// Create a new Explorer window, make the given page the home page, and show that page.
		/// </summary>
		/// <param name="homePage">The page to be used as the Explorer's home page</param>
		public Explorer(Page homePage) : this()
		{
			HomePage = homePage;
			frame.GoHome();
		}

		/// <value>
		/// The name of the application as it should appear in the Explorer's title bar.
		/// </value>
		public string ApplicationName
		{
			get
			{
				return applicationName;
			}
			set
			{
				applicationName = value;
				UpdateWindowTitle();
			}
		}

		/// <summary>
		/// Navigate back to the page selected from the Back button's dropdown menu.
		/// </summary>
		/// <param name="source">The menu item the user clicked</param>
		/// <param name="e">Arguments to the click event</param>
		private void BackButtonMenuItem_click(object source, EventArgs e)
		{
			int menuItemIndex = ((MenuItem) source).Index;
			frame.GoBack(menuItemIndex + 1);
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		/// <summary>
		/// Close the window.
		/// </summary>
		private void fileExit_Click (object sender, System.EventArgs e)
		{
			Close();
		}

		/// <summary>
		/// Navigate back to the page selected from the Forward button's dropdown menu.
		/// </summary>
		/// <param name="source">The menu item the user clicked</param>
		/// <param name="e">Arguments to the click event</param>
		private void ForwardButtonMenuItem_click(object source, EventArgs e)
		{
			int menuItemIndex = ((MenuItem) source).Index;
			frame.GoForward(menuItemIndex + 1);
		}

		/// <summary>
		/// The frame has navigated to a new page.
		/// </summary>
		/// <param name="sender">The frame that navigated</param>
		/// <param name="e">The arguments indicaing which page the frame navigated to</param>
		private void frame_Navigate (object sender, Navigation.NavigateEventArgs e)
		{
			UpdateWindowTitle();

			// Update the Back button's dropdown menu.
			string[] backStackPageTitles = frame.GetBackStackPageTitles(MAX_TOOLBAR_DROPDOWN_MENU_ITEMS);
			UpdateToolBarButtonMenu(backButton, backStackPageTitles, backButtonMenuItemHandler);

			// Update the Forward button's dropdown menu.
			string[] forwardStackPageTitles = frame.GetForwardStackPageTitles(MAX_TOOLBAR_DROPDOWN_MENU_ITEMS);
			UpdateToolBarButtonMenu(forwardButton, forwardStackPageTitles, forwardButtonMenuItemHandler);

			// Update the commands on the Go menu.
			goBack.Enabled = frame.CanGoBack;
			goForward.Enabled = frame.CanGoForward;
		}

		/// <summary>
		/// Handle the Go Back menu command.
		/// </summary>
		private void goBack_Click(object sender, System.EventArgs e)
		{
			frame.GoBack();
		}

		/// <summary>
		/// Handle the Go Forward menu command.
		/// </summary>
		private void goForward_Click(object sender, System.EventArgs e)
		{
			frame.GoForward();
		}

		/// <summary>
		/// Handle the Go Home menu command.
		/// </summary>
		private void goHome_Click(object sender, System.EventArgs e)
		{
			frame.GoHome();
		}

		/// <value>
		/// The home page used by this Explorer.
		/// </value>
		public Page HomePage
		{
			get
			{
				return frame.HomePage;
			}
			set
			{
				frame.HomePage = value;

				// Enable/disable commands for navigating to the home page.
				bool homePageExists = (frame.HomePage != null);
				homeButton.Enabled = homePageExists;
				goHome.Enabled = homePageExists;
			}
		}

		#region Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Explorer));
            this.fileExit = new System.Windows.Forms.MenuItem();
            this.backButton = new System.Windows.Forms.ToolBarButton();
            this.fileMenu = new System.Windows.Forms.MenuItem();
            this.homeButton = new System.Windows.Forms.ToolBarButton();
            this.forwardButton = new System.Windows.Forms.ToolBarButton();
            this.toolBarImages = new System.Windows.Forms.ImageList(this.components);
            this.navigationToolBar = new System.Windows.Forms.ToolBar();
            this.toolBarSeparator = new System.Windows.Forms.ToolBarButton();
            this.menuBar = new System.Windows.Forms.MainMenu(this.components);
            this.goMenu = new System.Windows.Forms.MenuItem();
            this.goBack = new System.Windows.Forms.MenuItem();
            this.goForward = new System.Windows.Forms.MenuItem();
            this.goMenuSeparator = new System.Windows.Forms.MenuItem();
            this.goHome = new System.Windows.Forms.MenuItem();
            this.frame = new Microsoft.Samples.Windows.Forms.Navigation.Frame();
            this.SuspendLayout();
            // 
            // fileExit
            // 
            this.fileExit.Index = 0;
            this.fileExit.Shortcut = System.Windows.Forms.Shortcut.AltF4;
            this.fileExit.ShowShortcut = false;
            this.fileExit.Text = "E&xit";
            this.fileExit.Click += new System.EventHandler(this.fileExit_Click);
            // 
            // backButton
            // 
            this.backButton.Enabled = false;
            this.backButton.ImageIndex = 0;
            this.backButton.Name = "backButton";
            this.backButton.Style = System.Windows.Forms.ToolBarButtonStyle.DropDownButton;
            // 
            // fileMenu
            // 
            this.fileMenu.Index = 0;
            this.fileMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.fileExit});
            this.fileMenu.Text = "&File";
            // 
            // homeButton
            // 
            this.homeButton.Enabled = false;
            this.homeButton.ImageIndex = 2;
            this.homeButton.Name = "homeButton";
            // 
            // forwardButton
            // 
            this.forwardButton.Enabled = false;
            this.forwardButton.ImageIndex = 1;
            this.forwardButton.Name = "forwardButton";
            this.forwardButton.Style = System.Windows.Forms.ToolBarButtonStyle.DropDownButton;
            // 
            // toolBarImages
            // 
            this.toolBarImages.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("toolBarImages.ImageStream")));
            this.toolBarImages.TransparentColor = System.Drawing.Color.Transparent;
            this.toolBarImages.Images.SetKeyName(0, "");
            this.toolBarImages.Images.SetKeyName(1, "");
            this.toolBarImages.Images.SetKeyName(2, "");
            // 
            // navigationToolBar
            // 
            this.navigationToolBar.Appearance = System.Windows.Forms.ToolBarAppearance.Flat;
            this.navigationToolBar.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[] {
            this.backButton,
            this.forwardButton,
            this.toolBarSeparator,
            this.homeButton});
            this.navigationToolBar.DropDownArrows = true;
            this.navigationToolBar.ImageList = this.toolBarImages;
            this.navigationToolBar.Location = new System.Drawing.Point(0, 0);
            this.navigationToolBar.Name = "navigationToolBar";
            this.navigationToolBar.ShowToolTips = true;
            this.navigationToolBar.Size = new System.Drawing.Size(256, 28);
            this.navigationToolBar.TabIndex = 0;
            this.navigationToolBar.TextAlign = System.Windows.Forms.ToolBarTextAlign.Right;
            this.navigationToolBar.Wrappable = false;
            this.navigationToolBar.ButtonClick += new System.Windows.Forms.ToolBarButtonClickEventHandler(this.navigationToolBar_ButtonClick);
            // 
            // toolBarSeparator
            // 
            this.toolBarSeparator.Name = "toolBarSeparator";
            this.toolBarSeparator.Style = System.Windows.Forms.ToolBarButtonStyle.Separator;
            // 
            // menuBar
            // 
            this.menuBar.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.fileMenu,
            this.goMenu});
            // 
            // goMenu
            // 
            this.goMenu.Index = 1;
            this.goMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.goBack,
            this.goForward,
            this.goMenuSeparator,
            this.goHome});
            this.goMenu.Text = "&Go";
            // 
            // goBack
            // 
            this.goBack.Enabled = false;
            this.goBack.Index = 0;
            this.goBack.Text = "&Back";
            this.goBack.Click += new System.EventHandler(this.goBack_Click);
            // 
            // goForward
            // 
            this.goForward.Enabled = false;
            this.goForward.Index = 1;
            this.goForward.Text = "&Forward";
            this.goForward.Click += new System.EventHandler(this.goForward_Click);
            // 
            // goMenuSeparator
            // 
            this.goMenuSeparator.Index = 2;
            this.goMenuSeparator.Text = "-";
            // 
            // goHome
            // 
            this.goHome.Enabled = false;
            this.goHome.Index = 3;
            this.goHome.Text = "&Home";
            this.goHome.Click += new System.EventHandler(this.goHome_Click);
            // 
            // frame
            // 
            this.frame.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.frame.Location = new System.Drawing.Point(0, 25);
            this.frame.Name = "frame";
            this.frame.Size = new System.Drawing.Size(256, 88);
            this.frame.TabIndex = 0;
            this.frame.Navigate += new Microsoft.Samples.Windows.Forms.Navigation.NavigateEventHandler(this.frame_Navigate);
            // 
            // Explorer
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(256, 113);
            this.Controls.Add(this.frame);
            this.Controls.Add(this.navigationToolBar);
            this.ForeColor = System.Drawing.SystemColors.WindowText;
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.KeyPreview = true;
            this.Menu = this.menuBar;
            this.Name = "Explorer";
            this.StartPosition = System.Windows.Forms.FormStartPosition.WindowsDefaultBounds;
            this.ResumeLayout(false);
            this.PerformLayout();

    }
		#endregion

		/// <summary>
		/// Handle navigation commands on the toolbar.
		/// </summary>
		protected void navigationToolBar_ButtonClick (object sender, System.Windows.Forms.ToolBarButtonClickEventArgs e)
		{
			if (e.Button == backButton)
			{
				frame.GoBack();
			}
			else if (e.Button == forwardButton)
			{
				frame.GoForward();
			}
			else if (e.Button == homeButton)
			{
				frame.GoHome();
			}
		}

		/// <summary>
		/// The window is closing.
		/// </summary>
		protected override void OnClosing(CancelEventArgs e)
		{
			// Ask the frame if it's okay to close now.
			e.Cancel = !frame.CanLeavePage;

			base.OnClosing(e);
		}

		/// <summary>
		/// Define keyboard shortcuts consistent with Microsoft Internet Explorer.
		/// </summary>
		protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
		{
			if (e.Alt)
			{
				// Navigation keyboard shortcuts.
				switch (e.KeyCode)
				{
					case Keys.Home:
						frame.GoHome();
						e.Handled = true;
						break;

					case Keys.Left:
						frame.GoBack();
						e.Handled = true;
						break;
					
					case Keys.Right:
						frame.GoForward();
						e.Handled = true;
						break;
				}
			}
			else
			{
                //Interferes with DataGrid page up and down
                //// Page scrolling keyboard shortcuts.
                //switch (e.KeyCode)
                //{
                //    case Keys.End:
                //        if (e.Control)
                //        {
                //            frame.PageEnd();
                //            e.Handled = true;
                //        }
                //        break;

                //    case Keys.Home:
                //        if (e.Control)
                //        {
                //            frame.PageHome();
                //            e.Handled = true;
                //        }
                //        break;

                //    case Keys.PageDown:
                //        frame.PageDown();
                //        e.Handled = true;
                //        break;

                //    case Keys.PageUp:
                //        frame.PageUp();
                //        e.Handled = true;
                //        break;
                //}
			}

			base.OnKeyDown(e);
		}

		/// <summary>
		/// Display the given array of page titles in the dropdown menu for the given
		/// toolbar button.
		/// </summary>
		/// <param name="button">The toolbar button</param>
		/// <param name="pageTitles">The array of page titles to display</param>
		/// <param name="clickEventHandler">The event handler that should be called when a page title is clicked</param>
		private void UpdateToolBarButtonMenu(ToolBarButton button, string[] pageTitles, EventHandler clickEventHandler)
		{
			if (pageTitles == null)
			{
				button.Enabled = false;
			}
			else
			{
				button.Enabled = true;

				if (button.DropDownMenu == null)
				{
					// This is the first time we're setting up the button's menu, so create the menu.
					button.DropDownMenu = new ContextMenu();
				}
				else
				{
					// Clear the existing contents of the button's menu.
					button.DropDownMenu.MenuItems.Clear();
				}

				// Add all the page titles to the menu.
				foreach (string pageTitle in pageTitles)
				{
					button.DropDownMenu.MenuItems.Add(pageTitle, clickEventHandler);
				}
			}
		}

		/// <summary>
		/// Update the title bar to shown the page and/or application name.
		/// </summary>
		private void UpdateWindowTitle()
		{
			string titleBarText;

			// Determine whether we have a page title, and application name, both, or neither.
			bool applicationHasTitle = (applicationName != null && applicationName.Length > 0);
			bool pageHasTitle = (frame.CurrentPage != null && frame.CurrentPage.Text.Length > 0);

			// Create an appropriate window title given the available information.
			if (applicationHasTitle && pageHasTitle)
			{
				// Include both the application name and page title, separated by a hyphen.
				titleBarText = frame.CurrentPage.Text + " - " + applicationName;
			}
			else if (applicationHasTitle && !pageHasTitle)
			{
				// Just show the application name.
				titleBarText = applicationName;
			}
			else if (!applicationHasTitle && pageHasTitle)
			{
				// Just show the page title.
				titleBarText = frame.CurrentPage.Text;
			}
			else
			{
				// Nothing to display; leave the title blank.
				titleBarText = String.Empty;
			}

			Text = titleBarText;
		}

		/// <summary>
		/// Handle special hardware buttons for navigation.
		/// </summary>
		/// <remarks>
		/// Certain hardware devices have special buttons for navigation. This includes mice like
		/// the Microsoft IntelliMouse Explorer and keyboards like the Microsoft Internet Keyboard Pro.
		/// Since the .NET framework doesn't currently provide native support for these hardware buttons,
		/// we implement such support by catching the relevant window messages ourselves. These messages
		/// are sent to the window, and not to an individual control. This means we have to implement
		/// support for these hardware buttons here, not in the code for the Frame control.
		/// </remarks>
		protected override void WndProc(ref Message m)
		{
			// Constant declarations from winuser.h
			const int WM_APPCOMMAND = 0x319;
			const int FAPPCOMMAND_MASK = 0xF000;
			const short APPCOMMAND_BROWSER_BACKWARD = 1;
			const short APPCOMMAND_BROWSER_FORWARD = 2;
			const short APPCOMMAND_BROWSER_HOME = 7;

			// True if we've handled the window message ourselves.
			bool handled = false;

			if (m.Msg == WM_APPCOMMAND)
			{
				uint LParam = (uint) m.LParam.ToInt32();
				short command = (short) ((LParam >> 16) & ~FAPPCOMMAND_MASK);

				switch (command)
				{
					case APPCOMMAND_BROWSER_BACKWARD:
						frame.GoBack();
						handled = true;
						break;

					case APPCOMMAND_BROWSER_FORWARD:
						frame.GoForward();
						handled = true;
						break;

					case APPCOMMAND_BROWSER_HOME:
						frame.GoHome();
						handled = true;
						break;
				}
			}

			if (!handled)
			{
				// We didn't handle the message, so allow the default processing to happen.
				base.WndProc(ref m);
			}
		}
	}
}
